﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Runtime;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;
using System.ComponentModel;

using PickGold.Arguments;
using PickGold.Handler;

using Block = System.Buffer;

namespace PickGold
{
	/// <summary/>
	[Serializable, ComVisible(true)]
	public class SerialReader : IDisposable
	{
		private readonly static object ReadedEventKey = new object();

		private readonly object SyncRoot = new object();

		private Stream _Data;
		private byte[] _Buffer;
		/// <summary>
		/// 缓存最后一个位置的索引，通常是缓存长度减一
		/// </summary>
		private int _BufferTail;
		/// <summary>
		/// 当前缓存的索引，当前索引处的值应该是无效的
		/// </summary>
		private int _BufferNext;
		/// <summary>
		/// 缓存第一个位置的索引，通常为零。
		/// </summary>
		private int _BufferHead;
		/// <summary>
		/// 剩余可读取字节数
		/// </summary>
		private int _RemainRead;
		/// <summary>
		/// 要查找的内容
		/// </summary>
		private byte[] _Search;
		/// <summary>
		/// 当前搜索的位置
		/// </summary>
		private int _SearchIndex;
		/// <summary>
		/// 当前最多可搜索字节数
		/// </summary>
		private int _SearchLimit;
		/// <summary>
		/// 当前查找的状态
		/// </summary>
		private IAsyncResult _Result;

		/// <summary/>
		private EventHandlerList _Events;

		/// <summary/>
		public SerialReader(Stream data) : this(data, new byte[8192]) { }

		/// <summary/>
		public SerialReader(Stream data, int buffer) : this(data, new byte[buffer]) { }

		/// <summary/>
		public SerialReader(Stream data, byte[] buffer)
		{
			this._Data = data;
			this._Buffer = buffer;
			this._BufferHead = 0;
			this._BufferNext = 0;
			this._BufferTail = this._Buffer.Length - 1;
		}

		/// <summary/>
		public event ProgressEventHandler Readed
		{
			add
			{
				if (this._Events == null)
					this._Events = new EventHandlerList();
				this._Events.AddHandler(ReadedEventKey, value);
			}
			remove
			{
				if (this._Events != null)
					this._Events.RemoveHandler(ReadedEventKey, value);
			}
		}

		/// <summary/>
		public EventHandlerList Events
		{
			get
			{
				return this._Events;
			}
		}

		/// <summary/>
		public Stream Data
		{
			set
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					if (this._Result != null)//已经在查找，禁止重复查找
						throw new IOException("Data Is Busy");

					this._Data = value;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
			}
			get
			{
				return this._Data;
			}
		}

		/// <summary/>
		public byte[] Buffer
		{
			get
			{
				return this._Buffer;
			}
		}

		/// <summary/>
		public int BufferHead
		{
			get
			{
				return this._BufferHead;
			}
		}

		/// <summary/>
		public int BufferNext
		{
			get
			{
				return this._BufferNext;
			}
		}

		/// <summary/>
		public int BufferTail
		{
			get
			{
				return this._BufferTail;
			}
		}

		/// <summary>
		/// 剩余内容，已读取内容
		/// </summary>
		public int RemainRead
		{
			set
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					if (this._Result != null)//已经在查找，禁止重复查找
						throw new IOException("Data Is Busy");

					this._RemainRead = value;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				return;
			}
			get
			{
				return this._RemainRead;
			}
		}

		/// <summary/>
		public bool IsBusy
		{
			get
			{
				if (this._Result == null)
					return false;

				return true;
			}
		}

		/// <summary/>
		public bool ResetBusy()
		{
			if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this.SyncRoot);
			try
			{
				if (this._Result == null)
					return true;

				if (!this._Result.IsCompleted)
					return false;

				//Buffer.Blo
				this._Result = null;
			}
			finally
			{
				Monitor.Exit(this.SyncRoot);
			}
			return true;
		}

		/// <summary/>
		public virtual IAsyncResult BeginFind(byte[] search, int limit, AsyncCallback callback, object state)
		{
			if (search == null)
				throw new ArgumentNullException(MethodBase.GetCurrentMethod().GetParameters()[0].Name);

			if (search.Length == 0)
				throw new ArgumentOutOfRangeException(MethodBase.GetCurrentMethod().GetParameters()[0].Name);

			if (limit >= 0 && limit < search.Length)
				throw new ArgumentOutOfRangeException(MethodBase.GetCurrentMethod().GetParameters()[1].Name);

			var ar = new AsyncResultWrap(int.MaxValue, null, callback, state);
			if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this.SyncRoot);
			try
			{
				if (this._Result != null)//已经在查找，禁止重复查找
					throw new IOException("Data Is Busy");

				this._Result = ar;
			}
			finally
			{
				Monitor.Exit(this.SyncRoot);
			}
			this._Search = new byte[search.Length];
			Block.BlockCopy(search, 0, this._Search, 0, search.Length);
			this._SearchIndex = 0;
			if (limit > 0)
				this._SearchLimit = this._BufferHead + limit;
			else
				this._SearchLimit = this._BufferTail + 1;
			if (this._SearchLimit > this._BufferTail + 1)
				this._SearchLimit = this._BufferTail + 1;
			if (this._BufferNext > 0 && this.InnserFind(ar, this._BufferNext, true) != 0)//先查找已存在的缓存数据
				return ar;

			var ds = this._Data;
			if (ds == null)
				return this._Result;

			if (this._BufferTail > this._SearchLimit)//如果缓存大小超过查找限制，则以最大查找限制来设置读取总量
				limit = this._SearchLimit - this._BufferNext;
			else
				limit = this._BufferTail - this._BufferNext + 1;//按剩余最大缓存大小读取要查找的数据
			try
			{
				ar.WrapResult = ds.BeginRead(this._Buffer, this._BufferNext, limit, this.InnerEndRead, new object[] { ar, ds, this._Buffer, this._BufferNext, limit, });
			}
			catch (Exception x)
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.SyncComplete(x);
			}
			return this._Result;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="result"></param>
		/// <returns>找到返回正数，未找到返回负数，其中被 <see cref="Readed"/> 中断返回负一；</returns>
		public virtual int EndFind(IAsyncResult result)
		{
			var ar = result as AsyncResultWrap;
			if (ar == null)
				throw new ArgumentException("Invalid argument");

			return (int)ar.WrapReturn;
		}

		/// <summary/>
		public virtual IAsyncResult BeginRead(int count, AsyncCallback callback, object state)
		{
			var ds = this._Data;
			if (this._BufferHead == int.MinValue && this._BufferTail == int.MinValue)
				return ds.BeginRead(this._Buffer, 0, this._BufferNext, callback, state);

			var ar = new AsyncResultWrap(1, null, callback, state);
			if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this.SyncRoot);
			try
			{
				if (this._Result != null)//已经在查找，禁止重复查找
					throw new IOException("Data Is Busy");

				this._Result = ar;
			}
			finally
			{
				Monitor.Exit(this.SyncRoot);
			}
			if (count > this._BufferTail - this._BufferNext + 1 || count < 0)//如果要读取的数量大于【缓存剩余空间】
				count = this._BufferTail - this._BufferNext + 1;//数量设置为缓存剩余空间数量
			if (count > this._RemainRead && this._RemainRead >= 0)//如果要读取的数量大于【剩余可读取数量】
				count = this._RemainRead;//数量设置为剩余可读取数量
			if (count == 0)//读取已结束，【缓存剩余空间】或【剩余可读取数】值为零
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.SyncComplete(count, null);
				return this._Result;
			}

			try
			{
				ar.WrapResult = ds.BeginRead(this._Buffer, this._BufferNext, count, this.InnerEndRead, new object[] { ar, ds, this._Buffer, this._BufferNext, count, });
			}
			catch (Exception x)
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.SyncComplete(x);
			}
			return this._Result;
		}

		/// <summary/>
		public int EndRead(IAsyncResult result)
		{
			var ar = result as AsyncResultWrap;
			if (ar == null)
			{
				if (this._BufferHead > 0 || this._BufferTail > 0)
					throw new ArgumentException(MethodBase.GetCurrentMethod().GetParameters()[0].Name);

				return this._Data.EndRead(result);
			}

			if (ar.WrapError != null)
				throw ar.WrapError;

			return (int)ar.WrapReturn;
		}

		/// <summary>
		/// 对每一步的实际读取进行处理，在重载中，对读取数据为零时应作休眠处理，返回 True 表示终止读取。
		/// </summary>
		/// <param name="e"></param>
		/// <returns>表示是否终止，返回 True 表示终止读取。</returns>
		public virtual void OnReaded(ProgressEventArgs e)
		{
			if (this._Events == null)
				return;

			var h = this._Events[ReadedEventKey] as ProgressEventHandler;
			if (h != null)
				h(this, e);
		}

		/// <summary/>
		private void InnerEndRead(IAsyncResult result)
		{
			//if (Thread.CurrentThread.IsThreadPoolThread && Fiber.QueueUserAsyncCallback(this.InnerEndRead, result))
			//	return;

			var i = 0;
			var os = result.AsyncState as object[];
			var ar = os[i++] as AsyncResultWrap;
			var ds = os[i++] as Stream;
			ar.Callbacks++;
			ar.WrapLast = DateTime.Now;
			try
			{
				i = ds.EndRead(result);
				if (i > 0)
					ar.Invalids = 0;
				else if (++ar.Invalids > byte.MaxValue)
					throw new IOException("Read zero bytes too many times.", ar.Invalids);
			}
			catch (Exception x)
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.Complete(x);
				return;
			}

			if (i > 0)
			{
				if (this._RemainRead >= 0)//减少剩余可读取数量
					this._RemainRead -= i;
				this._BufferNext += i;
			}
			if (this._Search == null)//不在查找状态
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.Complete(i);
				return;
			}

			var e = new ProgressEventArgs(i, this._BufferNext, 0, false);
			this.OnReaded(e);
			if (e.Handled)
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.Complete(-1);
				return;
			}

			if (i > 0)
			{
				if (this.InnserFind(ar, i, false) != 0)//先查找已存在的缓存数据
					return;
			}
			else
			{
				if (Fiber.QueueUserAction(this.EndRead, ar, BitUtil.K))
					return;
			}

			this.EndRead(ar);
		}

		/// <summary/>
		private void EndRead(AsyncResultWrap ar)
		{
			var ds = this._Data;
			var i = this._BufferNext;
			if (this._BufferTail > this._SearchLimit)//如果缓存大小超过查找限制，则以最大查找限制来设置读取总量
				i = this._SearchLimit - i;
			else
				i = this._BufferTail - i + 1;//按剩余最大缓存大小读取要查找的数据
			if (ds == null)
				return;

			try
			{
				ar.WrapResult = ds.BeginRead(this._Buffer, this._BufferNext, i, this.InnerEndRead, new object[] { ar, ds, this._Buffer, this._BufferNext, i, });
			}
			catch (Exception x)
			{
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.Complete(x);
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="ar">异步状态</param>
		/// <param name="i">当前未查找缓存数量</param>
		/// <param name="sync">是否为同步调用</param>
		/// <returns>非零表示查找结束，大于零为查找成功，小于零为超过查找限制，查找失败</returns>
		private int InnserFind(AsyncResultWrap ar, int i, bool sync)
		{
			var sl = this._Search.Length;
			var ii = this._BufferNext - this._SearchIndex - i;
			if (ii < 0)
			{
				ii = this._BufferNext - i;
				if (ii < 0)
					ii = 0;
			}
			this._SearchIndex = 0;
			for (; ii < this._BufferNext - this._SearchIndex; ii++)//缓存循环
			{
				var si = ii;
				for (; si < this._BufferNext && si < this._SearchLimit && this._SearchIndex < sl; )//查找循环，从缓存循环位置处进行查找循环
				{
					if (this._Buffer[si++] != this._Search[this._SearchIndex++])//比对查找，逐字节查找，应使用指针优化
					{
						this._SearchIndex = 0;//未找到，查找失败，进入下一轮缓存循环，缓存的下一个字节
						break;
					}
				}
				if (this._SearchIndex == sl)//找到，返回 大于零
				{
					this._Search = null;
					ar.CompletedSynchronously = sync;
					ar.Complete(si);
					return si;
				}
			}

			if (this._BufferNext >= this._SearchLimit)//超过查找限制还未找到，返回 小于零
			{
				this._Search = null;
				if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
					Fiber.ThrowLockTimeoutException(this.SyncRoot);
				try
				{
					this._Result = null;
				}
				finally
				{
					Monitor.Exit(this.SyncRoot);
				}
				ar.CompletedSynchronously = sync;
				ar.Complete(int.MinValue);
				return int.MinValue;
			}

			return 0;//查找未结束，需继续查找
		}

		/// <summary/>
		public int ResetBuffer(int count)
		{
			if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this.SyncRoot);
			try
			{
				if (this._Result != null)//已经在查找，禁止重复查找
					throw new IOException("Data Is Busy");
			}
			finally
			{
				Monitor.Exit(this.SyncRoot);
			}

			if (count > this._BufferNext - this._BufferHead || count <= 0)
			{
				this._BufferNext = 0;
				return count;
			}

			this._BufferNext -= count;
			Block.BlockCopy(this._Buffer, this._BufferNext, this._Buffer, 0, count);
			return count;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="output"></param>
		/// <param name="pass">直接取舍，抛弃对象中间计数环节</param>
		/// <returns></returns>
		public int ResetBuffer(Stream output, int pass = 0)
		{
			if (this._BufferHead == int.MinValue && this._BufferTail == int.MinValue)
			{
				output.Write(this._Buffer, 0, pass);
				return pass;
			}

			if (output == null && pass != 0 && this._BufferHead == 0 && this._BufferNext == 0)
			{
				this._BufferHead = int.MinValue;
				this._BufferNext = this._Buffer.Length;
				this._BufferTail = int.MinValue;
				return pass;
			}

			if (!Monitor.TryEnter(this.SyncRoot, Fiber.LockTimeout))
				Fiber.ThrowLockTimeoutException(this.SyncRoot);
			try
			{
				if (this._Result != null)//已经在查找，禁止重复查找
					throw new IOException("Data Is Busy");
			}
			finally
			{
				Monitor.Exit(this.SyncRoot);
			}

			var count = this._BufferNext - this._BufferHead;
			if (count <= 0)
			{
				if (pass != 0)
				{
					this._BufferHead = int.MinValue;
					this._BufferNext = this._Buffer.Length;
					this._BufferTail = int.MinValue;
				}
				return count;
			}

			output.Write(this._Buffer, this._BufferHead, count);
			if (pass != 0)
			{
				this._BufferHead = int.MinValue;
				this._BufferNext = this._Buffer.Length;
				this._BufferTail = int.MinValue;
			}
			else
			{
				this._BufferNext = 0;
			}
			return count;
		}

		/// <summary/>
		protected virtual void Dispose(bool disposing)
		{
			var d = this._Data;
			if (d != null)
			{
				d.Close();
				d.Dispose();
				this._Data = null;
			}
			this._SearchLimit = 0;
			this._SearchIndex = 0;
			this._Search = null;
			this._Buffer = null;
			this._BufferHead = 0;
			this._BufferNext = 0;
			this._BufferTail = 0;
		}

		/// <summary/>
		public void Dispose()
		{
			this.Dispose(false);
		}

		void IDisposable.Dispose()
		{
			this.Dispose(true);
		}
	}

	static partial class Class
	{
		#region invalid class SerialReader : Stream

		/// <summary/>
		[Serializable, ComVisible(true)]
		class SerialReader : Stream
		{
			#region inner class

			class ReadState
			{
				/// <summary>
				/// 回车标识
				/// </summary>
				public int cr;
				/// <summary>
				/// 换行标识
				/// </summary>
				public int lf;
				/// <summary>
				/// 新行标识
				/// </summary>
				public int nl;
				/// <summary>
				/// 最大限制
				/// </summary>
				public int ml;
				public int ct;
				public int bp;
				public byte[] bs;
				public char[] cs;
				public string se;
				public StringBuilder vs;
				public AsyncResultWrap rw;
			}

			#endregion

			internal int LastRead;
			internal bool Closable;
			internal byte[] ByteBuffer;
			internal int ByteLength;
			internal int BytePosition;
			internal char[] CharBuffer;
			internal StringBuilder InnerBuffer;
			internal Encoding InnerEncoding;
			internal Stream InnerStream;

			internal SerialReader() { }

			/// <summary/>
			public SerialReader(Stream stream) : this(stream, null, 0, true) { }

			/// <summary/>
			public SerialReader(Stream stream, Encoding encoding) : this(stream, encoding, 0, true) { }

			/// <summary/>
			public SerialReader(Stream stream, Encoding encoding, int bufferSize) : this(stream, encoding, 0, true) { }

			/// <summary/>
			public SerialReader(Stream stream, Encoding encoding, int bufferSize, bool closable)
			{
				if ((stream == null) || (encoding == null))
					throw new ArgumentNullException(MethodBase.GetCurrentMethod().GetParameters()[0].Name);

				if (!stream.CanRead)
					throw new ArgumentException("Stream Not Readable");

				this.InnerStream = stream;
				if (encoding == null)
					encoding = Encoding.UTF8;
				this.InnerEncoding = encoding;
				if (bufferSize <= 0)
					bufferSize = BitUtil.K;
				else if (bufferSize <= byte.MaxValue)
					bufferSize = byte.MaxValue + 1;
				this.ByteBuffer = new byte[bufferSize];
				this.ByteLength = 0;
				this.BytePosition = 0;
				this.Closable = closable;
				this.LastRead = 1;
			}

			/// <summary/>
			protected override void Dispose(bool disposing)
			{
				try
				{
					if (this.Closable && disposing && this.InnerStream != null)
						this.InnerStream.Close();
				}
				finally
				{
					this.InnerStream = null;
					this.InnerEncoding = null;
					this.ByteBuffer = null;
					this.CharBuffer = null;
					this.InnerBuffer = null;
				}
				base.Dispose(disposing);
			}

			private int ReadBuffer(bool move = false)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (this.ByteBuffer.Length > this.ByteLength)
				{
					this.LastRead = this.InnerStream.Read(this.ByteBuffer, this.ByteLength, this.ByteBuffer.Length);
					this.ByteLength += this.LastRead;
					return this.LastRead;
				}

				if (this.ByteLength > this.BytePosition)
				{
					if (!move)
						throw new ArgumentOutOfRangeException("有剩余数据必须移动处理，请传入移动剩余数据参数为 True 值！");

					var bs = new byte[this.ByteLength - this.BytePosition];
					Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, bs, 0, this.ByteLength - this.BytePosition);
					Buffer.BlockCopy(bs, 0, this.ByteBuffer, 0, this.ByteLength - this.BytePosition);
					this.BytePosition = 0;
				}
				this.LastRead = this.InnerStream.Read(this.ByteBuffer, 0, this.ByteBuffer.Length);
				this.ByteLength = this.LastRead;
				return this.LastRead;
			}

			private IAsyncResult BeginReadBuffer(bool move, AsyncCallback callback, object state)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (this.ByteBuffer.Length > this.ByteLength)
					return this.InnerStream.BeginRead(this.ByteBuffer, this.ByteLength, this.ByteBuffer.Length, callback, state);

				if (this.ByteLength > this.BytePosition)
				{
					if (!move)
						throw new ArgumentOutOfRangeException("有剩余数据必须移动处理，请传入移动剩余数据参数 move 为 True 值！");

					var bs = new byte[this.ByteLength - this.BytePosition];
					Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, bs, 0, this.ByteLength - this.BytePosition);
					Buffer.BlockCopy(bs, 0, this.ByteBuffer, 0, this.ByteLength - this.BytePosition);
					this.BytePosition = 0;
				}
				this.ByteLength = 0;
				return this.InnerStream.BeginRead(this.ByteBuffer, 0, this.ByteBuffer.Length, callback, state);
			}

			/// <summary/>
			public int ReadChars([In, Out] char[] buffer)
			{
				if (buffer == null)
					return 0;

				return this.ReadChars(buffer, 0);
			}

			/// <summary/>
			public IAsyncResult BeginReadChars([In, Out] char[] buffer, AsyncCallback callback, object state)
			{
				if (buffer == null)
					return AsyncResultWrap.SyncComplete(0, null, callback, state);

				return this.BeginReadChars(buffer, 0, callback, state);
			}

			/// <summary/>
			public int ReadChars([In, Out] char[] buffer, int index)
			{
				if (buffer == null)
					return 0;

				if (this.BytePosition >= this.ByteLength && this.ReadBuffer() == 0)
					return 0;

				var i = this.InnerEncoding.GetChars(this.ByteBuffer, this.BytePosition, this.ByteLength - this.BytePosition, buffer, index);
				this.BytePosition += this.InnerEncoding.GetByteCount(buffer, index, i);
				return i;
			}

			/// <summary/>
			public IAsyncResult BeginReadChars([In, Out] char[] buffer, int index, AsyncCallback callback, object state)
			{
				if (buffer == null)
					return AsyncResultWrap.SyncComplete(0, null, callback, state);

				var i = this.ByteLength - this.BytePosition;
				try
				{
					if (i <= 0)
					{
						var ar = new AsyncResultWrap(1, callback, state);
						ar.WrapResult = this.BeginReadBuffer(false, this.InnerReadChars, new object[] { ar, buffer, index, });
						return ar;
					}

					i = this.InnerEncoding.GetChars(this.ByteBuffer, this.BytePosition, i, buffer, index);
					if (i == 0)
					{
						var ar = new AsyncResultWrap(1, callback, state);
						ar.WrapResult = this.BeginReadBuffer(true, this.InnerReadChars, new object[] { ar, buffer, index, });
						return ar;
					}
				}
				catch (Exception x)
				{
					return AsyncResultWrap.SyncComplete(x, callback, state);
				}

				this.BytePosition += this.InnerEncoding.GetByteCount(buffer, index, i);
				return AsyncResultWrap.SyncComplete(i, null, callback, state);
			}

			private void InnerReadChars(IAsyncResult result)
			{
				if (Thread.CurrentThread.IsThreadPoolThread && Fiber.QueueUserAsyncCallback(this.InnerReadChars, result))
					return;

				var os = result.AsyncState as object[];
				var ar = os[0] as AsyncResultWrap;
				ar.WrapResult = result;
				if (this.BytePosition >= this.ByteLength)
				{
					ar.Complete(0, null);
					return;
				}

				var cs = os[1] as char[];
				var ci = (int)os[2];
				this.LastRead = this.InnerStream.EndRead(result);
				this.ByteLength += this.LastRead;
				var i = this.InnerEncoding.GetChars(this.ByteBuffer, this.BytePosition, this.ByteLength - this.BytePosition, cs, ci);
				this.BytePosition += this.InnerEncoding.GetByteCount(cs, ci, i);
				ar.Complete(i, null);
			}

			/// <summary/>
			public int EndReadChars(IAsyncResult asyncResult)
			{
				var ar = asyncResult as IAsyncResultWrap;
				if (ar.WrapError != null)
					throw ar.WrapError;

				return (int)ar.WrapReturn;
			}

			/// <summary>
			/// 读取行，行尾带换行符，若为流结尾则不一定带换行符，如果超过最大数据则返回 Null
			/// </summary>
			/// <param name="max">返回最大字符数，小于零表示不限制</param>
			/// <returns>返回行，行尾带换行符，若为流结尾则不一定带换行符，如果超过最大数据则返回 Null</returns>
			public string ReadLine(int max)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (max == 0)
					return string.Empty;

				var rs = new ReadState();
				rs.cr = 0;//回车标识
				rs.lf = 0;//换行标识
				rs.ct = 0;
				rs.bs = this.ByteBuffer;
				rs.bp = this.BytePosition;
				rs.vs = this.InnerBuffer;
				rs.ml = max;
				rs.nl = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;//主作用：新行标识
				rs.cs = this.CharBuffer;
				if (rs.cs == null || rs.cs.Length < rs.nl)
					this.CharBuffer = rs.cs = new char[rs.nl];
				rs.nl = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
				if (rs.nl % BitUtil.K > 0)
					rs.nl = BitUtil.K * (rs.nl / BitUtil.K + 1);
				if (this.InnerBuffer == null)
					this.InnerBuffer = rs.vs = new StringBuilder();
				else
					this.InnerBuffer.Clear();
				if (rs.nl > this.ByteBuffer.Length - this.BytePosition)
				{
					this.ByteBuffer = new byte[rs.nl > this.ByteBuffer.Length ? rs.nl : this.ByteBuffer.Length];
					this.ByteLength -= this.BytePosition;
					Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
					this.BytePosition = 0;
					rs.bs = this.ByteBuffer;
					rs.bp = this.BytePosition;
				}
				rs.nl = 0;
				for (; ; )
				{
					if (this.ByteLength <= this.BytePosition && this.ReadBuffer() == 0)
					{
						if (rs.nl > 0)
						{
							rs.nl = rs.ct - rs.nl;
							this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
							this.Dispose();
							return rs.vs.ToString().Remove(rs.vs.Length - rs.nl);
						}

						return string.Empty;
					}

					rs.ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
					if (rs.ct == 0)
						continue;

					rs.vs.Append(rs.cs, 0, rs.ct);
					rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, rs.ct);
					for (rs.nl = 0; rs.nl < rs.ct; rs.nl++)
					{
						switch (rs.cs[rs.nl])
						{
							case '\r':
								rs.cr++;
								break;
							case '\n':
								rs.lf++;
								break;
						}
						if (rs.lf > 0 || rs.cr > 1)
							break;
					}
					if (rs.lf > 0 || rs.cr > 1)
					{
						rs.nl = rs.ct - rs.nl;
						this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
						return rs.vs.ToString().Remove(rs.vs.Length - rs.nl);
					}

					if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
						break;

					if (rs.cr == 0)
						rs.nl = 0;
				}
				//this._BytePosition = bp;
				//return vs.ToString();
				if (rs.nl > 0)
				{
					rs.nl = rs.ct - rs.nl;
					this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
					return rs.vs.ToString().Remove(rs.vs.Length - rs.nl);
				}

				return null;
			}

			/// <summary>
			/// 读取行，行尾带换行符，若为流结尾则不一定带换行符，如果超过最大数据则返回 Null
			/// </summary>
			/// <param name="max">返回最大字符数，小于零表示不限制</param>
			/// <param name="callback"></param>
			/// <param name="state"></param>
			/// <returns></returns>
			public IAsyncResult BeginReadLine(int max, AsyncCallback callback, object state)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (max == 0)
					return AsyncResultWrap.SyncComplete(string.Empty, null, callback, state);

				var rs = new ReadState();
				rs.rw = new AsyncResultWrap(-1, callback, state);
				rs.cr = 0;//回车标识
				rs.lf = 0;//换行标识
				rs.ct = 0;
				rs.bs = this.ByteBuffer;
				rs.bp = this.BytePosition;
				rs.vs = this.InnerBuffer;
				rs.ml = max;
				rs.nl = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;//主作用：新行标识
				rs.cs = this.CharBuffer;
				if (rs.cs == null || rs.cs.Length < rs.nl)
					this.CharBuffer = rs.cs = new char[rs.nl];
				rs.nl = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
				if (rs.nl % BitUtil.K > 0)
					rs.nl = BitUtil.K * (rs.nl / BitUtil.K + 1);
				if (this.InnerBuffer == null)
					this.InnerBuffer = rs.vs = new StringBuilder();
				else
					this.InnerBuffer.Clear();
				if (rs.nl > this.ByteBuffer.Length - this.BytePosition)
				{
					this.ByteBuffer = new byte[rs.nl > this.ByteBuffer.Length ? rs.nl : this.ByteBuffer.Length];
					this.ByteLength -= this.BytePosition;
					Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
					this.BytePosition = 0;
					rs.bs = this.ByteBuffer;
					rs.bp = this.BytePosition;
				}
				rs.nl = 0;
				rs.rw.WrapTag = rs;
				if (this.BytePosition >= this.ByteLength)
					rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadLine, rs);
				else
					this.InnerReadLine(rs.rw);
				return rs.rw;
			}

			private void InnerReadLine(IAsyncResult result)
			{
				if (Thread.CurrentThread.IsThreadPoolThread && Fiber.QueueUserAsyncCallback(this.InnerReadLine, result))
					return;

				var rs = result.AsyncState as ReadState;
				if (rs == null)
				{
					var ar = result as IAsyncResultWrap;
					rs = ar.WrapTag as ReadState;
				}
				else
				{
					try
					{
						this.LastRead = this.InnerStream.EndRead(result);
					}
					catch (Exception x)
					{
						rs.rw.Complete(x);
						return;
					}

					if (this.LastRead == 0)
					{
						if (rs.nl > 0)
						{
							rs.nl = rs.ct - rs.nl;
							this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
							this.Dispose();
							rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - rs.nl), null);
							return;
						}

						rs.rw.Complete(string.Empty, null);
						return;
					}

					this.ByteLength += this.LastRead;
				}

				rs.ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
				if (rs.ct == 0)
				{
					rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadLine, rs);
					return;
				}

				rs.vs.Append(rs.cs, 0, rs.ct);
				rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, rs.ct);
				for (rs.nl = 0; rs.nl < rs.ct; rs.nl++)
				{
					switch (rs.cs[rs.nl])
					{
						case '\r':
							rs.cr++;
							break;
						case '\n':
							rs.lf++;
							break;
					}
					if (rs.lf > 0 || rs.cr > 1)
						break;
				}
				if (rs.lf > 0 || rs.cr > 1)
				{
					rs.nl = rs.ct - rs.nl;
					this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
					rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - rs.nl), null);
					return;
				}

				if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
				{
					if (rs.nl > 0)
					{
						rs.nl = rs.ct - rs.nl;
						this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, rs.ct - rs.nl, rs.nl);
						rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - rs.nl), null);
						return;
					}

					//this._BytePosition = bp;
					//rs.rw.Complete(rs.vs.ToString(), null);
					rs.rw.Complete(null, null);
					return;
				}

				if (rs.cr == 0)
					rs.nl = 0;
				rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadLine, rs);
			}

			/// <summary/>
			public string EndReadLine(IAsyncResult asyncResult)
			{
				var ar = asyncResult as IAsyncResultWrap;
				if (ar.WrapError != null)
					throw ar.WrapError;

				return (string)ar.WrapReturn;
			}

			/// <summary>
			/// 读取到流结束的文本，如果超过最大数据则返回 Null
			/// </summary>
			/// <param name="max">返回最大字符数，小于零表示不限制</param>
			/// <returns>返回到流结束文本，如果超过最大数据则返回 Null</returns>
			public string ReadToEnd(int max)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (max == 0)
					return string.Empty;

				var rs = new ReadState();
				rs.vs = this.InnerBuffer;
				rs.bs = this.ByteBuffer;
				rs.ml = max;
				rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
				rs.cs = this.CharBuffer;
				if (rs.cs == null || rs.cs.Length < rs.bp)
					this.CharBuffer = rs.cs = new char[rs.bp];
				rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
				if (rs.bp % BitUtil.K > 0)
					rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
				if (this.InnerBuffer == null)
					this.InnerBuffer = rs.vs = new StringBuilder();
				else
					this.InnerBuffer.Clear();
				if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
				{
					this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
					this.ByteLength -= this.BytePosition;
					Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
					this.BytePosition = 0;
					rs.bs = this.ByteBuffer;
				}
				rs.bp = this.BytePosition;
				for (; ; )
				{
					if (this.ByteLength <= this.BytePosition && this.ReadBuffer() == 0)
					{
						this.BytePosition = rs.bp;
						this.Dispose();
						return rs.vs.ToString();
					}

					var ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
					if (ct == 0)
						continue;

					rs.vs.Append(rs.cs, 0, ct);
					rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, ct);
					if (max >= 0 && rs.vs.Length >= max)
						break;
				}
				//this._BytePosition = bp;
				//return vs.ToString();
				return null;
			}

			/// <summary>
			/// 读取到流结束的文本，如果超过最大数据则返回 Null
			/// </summary>
			/// <param name="max">返回最大字符数，小于零表示不限制</param>
			/// <param name="callback"></param>
			/// <param name="state"></param>
			/// <returns></returns>
			public IAsyncResult BeginReadToEnd(int max, AsyncCallback callback, object state)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (max == 0)
					return AsyncResultWrap.SyncComplete(string.Empty, null, callback, state);

				var rs = new ReadState();
				rs.rw = new AsyncResultWrap(-1, callback, state);
				rs.vs = this.InnerBuffer;
				rs.bs = this.ByteBuffer;
				rs.ml = max;
				rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
				rs.cs = this.CharBuffer;
				if (rs.cs == null || rs.cs.Length < rs.bp)
					this.CharBuffer = rs.cs = new char[rs.bp];
				rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
				if (rs.bp % BitUtil.K > 0)
					rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
				if (this.InnerBuffer == null)
					this.InnerBuffer = rs.vs = new StringBuilder();
				else
					this.InnerBuffer.Clear();
				if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
				{
					this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
					this.ByteLength -= this.BytePosition;
					Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
					this.BytePosition = 0;
					rs.bs = this.ByteBuffer;
				}
				rs.bp = this.BytePosition;
				if (this.BytePosition >= this.ByteLength)
					rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
				else
					this.InnerReadToEnd(rs.rw);
				return rs.rw;
			}

			private void InnerReadToEnd(IAsyncResult result)
			{
				if (Thread.CurrentThread.IsThreadPoolThread && Fiber.QueueUserAsyncCallback(this.InnerReadToEnd, result))
					return;

				var rs = result.AsyncState as ReadState;
				if (rs == null)
				{
					var ar = result as IAsyncResultWrap;
					rs = ar.WrapTag as ReadState;
				}
				else
				{
					try
					{
						this.LastRead = this.InnerStream.EndRead(result);
					}
					catch (Exception x)
					{
						rs.rw.Complete(x);
						return;
					}

					if (this.LastRead == 0)
					{
						this.BytePosition = rs.bp;
						this.Dispose();
						rs.rw.Complete(rs.vs.ToString(), null);
						return;
					}

					this.ByteLength += this.LastRead;
				}

				var ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, 0);
				if (ct == 0)
				{
					rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
					return;
				}

				if (rs.se == null)
				{
					rs.vs.Append(rs.cs, 0, ct);
					rs.bp += this.InnerEncoding.GetByteCount(rs.cs, 0, ct);
				}
				else
				{

					rs.vs.Append(rs.cs, rs.nl, rs.ct);
					rs.bp += this.InnerEncoding.GetByteCount(rs.cs, rs.nl, rs.ct);
					for (var i = 0; i < ct; i++)
					{
						var ii = 0;
						for (; ii < rs.nl; ii++)
						{
							if (rs.cs[i] != rs.se[ii])
								break;
						}
						if (ii >= rs.nl)
						{
							i += rs.nl;
							this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, i, ct - i);
							rs.rw.Complete(rs.vs.ToString().Remove(rs.vs.Length - ct + i), null);
						}
					}
				}
				if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
				{
					//this._BytePosition = bp;
					//rs.rw.Complete(rs.vs.ToString(), null);
					rs.rw.Complete(null, null);
					return;
				}

				rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
			}

			/// <summary/>
			public string EndReadToEnd(IAsyncResult asyncResult)
			{
				var ar = asyncResult as IAsyncResultWrap;
				if (ar.WrapError != null)
					throw ar.WrapError;

				return (string)ar.WrapReturn;
			}

			/// <summary>
			/// 读取字符串，行尾带结束符，若为流结尾则不一定带结束符，如果超过最大数据则返回 Null
			/// </summary>
			/// <param name="max">返回最大字符数，小于零表示不限制</param>
			/// <param name="end">结束标识字符串</param>
			/// <returns>返字符串，行尾带结束符，若为流结尾则不一定带结束符，如果超过最大数据则返回 Null</returns>
			public string ReadToEnd(int max, string end)
			{
				if (string.IsNullOrEmpty(end))
					return this.ReadToEnd(max);

				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (max == 0)
					return string.Empty;

				var rs = new ReadState();
				rs.se = end;
				rs.nl = rs.se.Length;
				rs.vs = this.InnerBuffer;
				rs.bs = this.ByteBuffer;
				rs.ml = max;
				rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
				rs.cs = this.CharBuffer;
				if (rs.cs == null || rs.cs.Length < rs.bp)
					this.CharBuffer = rs.cs = new char[rs.bp];
				rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
				if (rs.bp % BitUtil.K > 0)
					rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
				if (this.InnerBuffer == null)
					this.InnerBuffer = rs.vs = new StringBuilder();
				else
					this.InnerBuffer.Clear();
				if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
				{
					this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
					this.ByteLength -= this.BytePosition;
					Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
					this.BytePosition = 0;
					rs.bs = this.ByteBuffer;
				}
				rs.bp = this.BytePosition;
				for (; ; )
				{
					if (this.ByteLength <= this.BytePosition && this.ReadBuffer() == 0)
					{
						this.BytePosition = rs.bp;
						this.Dispose();
						return rs.vs.ToString();
					}

					var ct = this.InnerEncoding.GetChars(rs.bs, rs.bp, this.ByteLength - rs.bp, rs.cs, rs.nl) + rs.nl;
					if (ct == rs.nl)
						continue;

					rs.vs.Append(rs.cs, rs.nl, rs.ct);
					rs.bp += this.InnerEncoding.GetByteCount(rs.cs, rs.nl, rs.ct);
					for (var i = 0; i < ct; i++)
					{
						var ii = 0;
						for (; ii < rs.nl; ii++)
						{
							if (rs.cs[i] != end[ii])
								break;
						}
						if (ii >= rs.nl)
						{
							i += rs.nl;
							this.BytePosition = rs.bp - this.InnerEncoding.GetByteCount(rs.cs, i, ct - i);
							return rs.vs.ToString().Remove(rs.vs.Length - ct + i);
						}
					}
					if (rs.ml >= 0 && rs.vs.Length >= rs.ml)
						break;
				}
				//this._BytePosition = bp;
				//return vs.ToString();
				return null;
			}

			/// <summary>
			/// 读取字符串，行尾带结束符，若为流结尾则不一定带结束符，如果超过最大数据则返回 Null
			/// </summary>
			/// <param name="max">返回最大字符数，小于零表示不限制</param>
			/// <param name="end">结束标识字符串</param>
			/// <param name="callback"></param>
			/// <param name="state"></param>
			/// <returns></returns>
			public IAsyncResult ReadToEnd(int max, string end, AsyncCallback callback, object state)
			{
				if (string.IsNullOrEmpty(end))
					return this.BeginReadToEnd(max, callback, state);

				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (max == 0)
					return AsyncResultWrap.SyncComplete(string.Empty, null, callback, state);

				var rs = new ReadState();
				rs.rw = new AsyncResultWrap(-1, callback, state);
				rs.se = end;
				rs.nl = rs.se.Length;
				rs.vs = this.InnerBuffer;
				rs.bs = this.ByteBuffer;
				rs.ml = max;
				rs.bp = rs.ml > 0 ? (rs.ml > BitUtil.K ? BitUtil.K : rs.ml) : BitUtil.K;
				rs.cs = this.CharBuffer;
				if (rs.cs == null || rs.cs.Length < rs.bp)
					this.CharBuffer = rs.cs = new char[rs.bp];
				rs.bp = this.InnerEncoding.GetMaxByteCount(rs.cs.Length);
				if (rs.bp % BitUtil.K > 0)
					rs.bp = BitUtil.K * (rs.bp / BitUtil.K + 1);
				if (this.InnerBuffer == null)
					this.InnerBuffer = rs.vs = new StringBuilder();
				else
					this.InnerBuffer.Clear();
				if (rs.bp > this.ByteBuffer.Length - this.BytePosition)
				{
					this.ByteBuffer = new byte[rs.bp > this.ByteBuffer.Length ? rs.bp : this.ByteBuffer.Length];
					this.ByteLength -= this.BytePosition;
					Buffer.BlockCopy(rs.bs, this.BytePosition, this.ByteBuffer, 0, this.ByteLength);
					this.BytePosition = 0;
					rs.bs = this.ByteBuffer;
				}
				rs.bp = this.BytePosition;
				if (this.BytePosition >= this.ByteLength)
					rs.rw.WrapResult = this.BeginReadBuffer(false, this.InnerReadToEnd, rs);
				else
					this.InnerReadToEnd(rs.rw);
				return rs.rw;
			}

			/// <summary/>
			public virtual Stream BaseStream
			{
				get
				{
					return this.InnerStream;
				}
			}

			/// <summary/>
			public virtual Encoding CurrentEncoding
			{
				get
				{
					return this.InnerEncoding;
				}
			}

			/// <summary/>
			public bool EndOfStream
			{
				get
				{
					if (this.InnerStream == null)
						return true;

					if (this.LastRead == 0)
						return true;

					return false;
				}
			}

			/// <summary/>
			public bool Disposed
			{
				get
				{
					if (this.InnerStream == null)
						return true;

					return false;
				}
			}

			#region Stream

			/// <summary/>
			public override bool CanRead
			{
				get
				{
					if (this.InnerStream == null)
						throw new ObjectDisposedException(this.GetType().Name);

					return this.InnerStream.CanRead;
				}
			}

			/// <summary/>
			public override bool CanSeek
			{
				get
				{
					if (this.InnerStream == null)
						throw new ObjectDisposedException(this.GetType().Name);

					return this.InnerStream.CanSeek;
				}
			}

			/// <summary/>
			public override bool CanTimeout
			{
				get
				{
					return this.InnerStream.CanTimeout;
				}
			}

			/// <summary/>
			public override bool CanWrite
			{
				get
				{
					if (this.InnerStream == null)
						throw new ObjectDisposedException(this.GetType().Name);

					return this.InnerStream.CanWrite;
				}
			}

			/// <summary/>
			public override void Flush()
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				this.InnerStream.Flush();
			}

			/// <summary/>
			public override long Length
			{
				get
				{
					if (this.InnerStream == null)
						throw new ObjectDisposedException(this.GetType().Name);

					return this.InnerStream.Length;
				}
			}

			/// <summary/>
			public override long Position
			{
				get
				{
					if (this.InnerStream == null)
						throw new ObjectDisposedException(this.GetType().Name);

					return this.InnerStream.Position - this.ByteLength + this.BytePosition;
				}
				set
				{
					if (this.InnerStream == null)
						throw new ObjectDisposedException(this.GetType().Name);

					this.InnerStream.Position = value;
					this.BytePosition = 0;
					this.ByteLength = 0;
				}
			}

			/// <summary/>
			public override int ReadTimeout
			{
				get
				{
					return this.InnerStream.ReadTimeout;
				}
				set
				{
					this.InnerStream.ReadTimeout = value;
				}
			}

			/// <summary/>
			public override int WriteTimeout
			{
				get
				{
					return this.InnerStream.WriteTimeout;
				}
				set
				{
					this.InnerStream.WriteTimeout = value;
				}
			}

			/// <summary/>
			public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (this.ByteLength > this.BytePosition)
				{
					if (count > this.ByteLength - this.BytePosition)
						count = this.ByteLength - this.BytePosition;
					Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, buffer, offset, count);
					this.BytePosition += count;
					return AsyncResultWrap.SyncComplete(count, null, callback, state);
				}

				var ar = new AsyncResultWrap(1, callback, state);
				try
				{
					ar.WrapResult = this.InnerStream.BeginRead(buffer, offset, count, this.InnerRead, ar);
				}
				catch (Exception x)
				{
					return ar.Complete(x);
				}

				return ar;
			}

			/// <summary/>
			public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
			{
				if (this.ByteLength > this.BytePosition)
					this.Seek(this.BytePosition - this.ByteLength, SeekOrigin.Current);
				try
				{
					var ar = new AsyncResultWrap(1, callback, state);
					ar.WrapResult = this.InnerStream.BeginWrite(buffer, offset, count, this.InnerWrite, ar);
					return ar;
				}
				catch
				{
					if (this.ByteLength > this.BytePosition)
						this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
					throw;
				}
			}

			/// <summary/>
			public override void Close()
			{
				this.Dispose();
			}

			private void InnerRead(IAsyncResult result)
			{
				if (Thread.CurrentThread.IsThreadPoolThread && Fiber.QueueUserAsyncCallback(this.InnerRead, result))
					return;

				var rw = result.AsyncState as AsyncResultWrap;
				rw.WrapResult = result;
				try
				{
					this.LastRead = this.InnerStream.EndRead(result);
					this.BytePosition = 0;
					this.ByteLength = 0;
					rw.WrapReturn = this.LastRead;
					rw.Complete(this.LastRead, null);
				}
				catch (Exception x)
				{
					rw.Complete(x);
				}
			}

			/// <summary/>
			public override int EndRead(IAsyncResult asyncResult)
			{
				var ar = asyncResult as IAsyncResultWrap;
				if (ar.WrapError != null)
					throw ar.WrapError;

				return (int)ar.WrapReturn;
			}

			private void InnerWrite(IAsyncResult result)
			{
				if (Thread.CurrentThread.IsThreadPoolThread && Fiber.QueueUserAsyncCallback(this.InnerWrite, result))
					return;

				var rw = result.AsyncState as AsyncResultWrap;
				rw.WrapResult = result;
				try
				{
					this.InnerStream.EndWrite(result);
					if (this.InnerStream.Length > this.InnerStream.Position)
						this.LastRead = 1;
					this.BytePosition = 0;
					this.ByteLength = 0;
					rw.Complete();
				}
				catch (Exception x)
				{
					if (this.ByteLength > this.BytePosition)
						this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
					rw.Complete(x);
				}
			}

			/// <summary/>
			public override void EndWrite(IAsyncResult asyncResult)
			{
				var ar = asyncResult as IAsyncResultWrap;
				if (ar.WrapError != null)
					throw ar.WrapError;
			}

			public int Read(byte[] buffer)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (buffer == null)
					return 0;

				return this.Read(buffer, 0, buffer.Length);
			}

			/// <summary/>
			public override int Read(byte[] buffer, int offset, int count)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (buffer == null)
					return 0;

				if (this.ByteLength > this.BytePosition)
				{
					if (count > this.ByteLength - this.BytePosition)
						count = this.ByteLength - this.BytePosition;
					Buffer.BlockCopy(this.ByteBuffer, this.BytePosition, buffer, offset, count);
					this.BytePosition += count;
					return count;
				}

				this.LastRead = this.InnerStream.Read(buffer, offset, count);
				this.BytePosition = 0;
				this.ByteLength = 0;
				return this.LastRead;
			}

			/// <summary/>
			public override int ReadByte()
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (this.ByteLength > this.BytePosition)
				{
					this.BytePosition++;
					return this.ByteBuffer[this.BytePosition];
				}

				var i = this.InnerStream.ReadByte();
				this.BytePosition = 0;
				this.ByteLength = 0;
				if (i >= 0)
					this.LastRead = 1;
				else
					this.LastRead = 0;
				return i;
			}

			/// <summary/>
			public override long Seek(long offset, SeekOrigin origin)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				var i = this.InnerStream.Seek(offset, origin);
				this.BytePosition = 0;
				this.ByteLength = 0;
				if (this.InnerStream.Length == i)
					this.LastRead = 0;
				return i;
			}

			/// <summary/>
			public override void SetLength(long value)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				var p = this.InnerStream.Position;
				this.InnerStream.SetLength(value);
				p = value - p;
				if (p >= 0L)
				{
					this.LastRead = this.ByteLength - this.BytePosition;
					return;
				}

				this.ByteLength = (int)(this.ByteLength + p);
				this.LastRead = this.ByteLength - this.BytePosition;
				if (this.LastRead > 0)
					return;

				this.BytePosition = 0;
				this.ByteLength = 0;
			}

			/// <summary/>
			public void Write(byte[] buffer)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (buffer == null)
					return;

				this.Write(buffer, 0, buffer.Length);
			}

			/// <summary/>
			public override void Write(byte[] buffer, int offset, int count)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (buffer == null)
					return;

				if (this.ByteLength > this.BytePosition)
					this.Seek(this.BytePosition - this.ByteLength, SeekOrigin.Current);
				try
				{
					this.InnerStream.Write(buffer, offset, count);
				}
				catch
				{
					if (this.ByteLength > this.BytePosition)
						this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
					throw;
				}

				if (this.InnerStream.Length > this.InnerStream.Position)
					this.LastRead = 1;
				this.BytePosition = 0;
				this.ByteLength = 0;
			}

			/// <summary/>
			public override void WriteByte(byte value)
			{
				if (this.InnerStream == null)
					throw new ObjectDisposedException(this.GetType().Name);

				if (this.ByteLength > this.BytePosition)
					this.Seek(this.BytePosition - this.ByteLength, SeekOrigin.Current);
				try
				{
					this.InnerStream.WriteByte(value);
				}
				catch
				{
					if (this.ByteLength > this.BytePosition)
						this.Seek(this.ByteLength - this.BytePosition, SeekOrigin.Current);
					throw;
				}

				if (this.InnerStream.Length > this.InnerStream.Position)
					this.LastRead = 1;
				this.BytePosition = 0;
				this.ByteLength = 0;
			}

			#endregion
		}

		#endregion
	}
}
